package common.util.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.CharSet;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * Author: dong peng
 * Date: 2018/2/2
 * Time: 14:17
 */


public class HttpClientDemo {

    // 官方文档给的第一个列子
    public static void simpleRequest() throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("http://ifeve.com/httpclient-1-1/");
        CloseableHttpResponse response = httpClient.execute(httpGet);

        try {
            // do
            HttpEntity entity = response.getEntity();
            if(entity != null) {
                InputStream inputStream = entity.getContent();

                // 缓存实体, 有些场景下需要实体被重复读取
//                entity = new BufferedHttpEntity(entity);

                try {
                    // do something

                }finally {
                    inputStream.close();
                }
            }
        }finally {
            // 关闭内容流和关闭响应之间的差别在于，
            // 前者将试图通过消耗实体内容来维持底层连接可用，
            // 而后者将立即关闭和丢弃连接。
            response.close();
        }
    }

    // 官方提供了URIBuilder类来构建请求资源
    public static URI bulidUri() throws URISyntaxException {
        URI uri = new URIBuilder()
                .setScheme("http")
                .setHost("www.baidu.com")
                .setPath("")
                .setParameter("","")
                .setParameter("","")
                .build();

        return uri;
    }

    // http请求返回消息时，消息第一行包含基本协议，以及后面跟的数字
    public static void basicReponse() {
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");


        System.out.println(response.getProtocolVersion());
        System.out.println(response.getStatusLine().getStatusCode());
        System.out.println(response.getStatusLine().getReasonPhrase());
        System.out.println(response.getStatusLine().toString());
    }

    /*
    * http可以包含多个描述该消息属性的头部，诸如内容长度，内容类型等
    * */
    public static void header() {
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
        response.addHeader("Set-Cookie","c1=a; path=/; domain=localhost;");
        response.addHeader("Set-Cookie","c2=b; path=/, c3=c; domain=localhost");

        Header h1 = response.getFirstHeader("Set-Cookie");
        System.out.println(h1);

        Header h2 = response.getLastHeader("Set-Cookie");
        System.out.println(h2);

        Header[] hs = response.getHeaders("Set-Cookie");
        System.out.println(hs.length);
    }

    // 遍历所有头信息
    public static void getAllHeader() {
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
                HttpStatus.SC_OK, "OK");
        response.addHeader("Set-Cookie",
                "c1=a; path=/; domain=localhost");
        response.addHeader("Set-Cookie",
                "c2=b; path=\"/\", c3=c; domain=\"localhost\"");

        HeaderIterator it = response.headerIterator("Set-Cookie");

        // 也可以像下面更方便的遍历
//        HeaderElementIterator it2 = new BasicHeaderElementIterator(
//                response.headerIterator("Set-Cookie"));

        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }

    // http消息请求/响应过程中允许携带实体
    public static void createEntity() throws IOException {
        StringEntity stringEntity = new StringEntity("important message", ContentType.create("text/plain","UTF-8"));

        System.out.println(stringEntity.getContentType());
        System.out.println(stringEntity.getContentLength());
        System.out.println(EntityUtils.toString(stringEntity));
        System.out.println(EntityUtils.toByteArray(stringEntity).length);
    }

    // 模拟一个HTML 表单
    public static void createForm() {
        List<NameValuePair> formParams = new ArrayList<>();
        formParams.add(new BasicNameValuePair("param1","value1"));
        formParams.add(new BasicNameValuePair("param2","value2"));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
        entity.setChunked(true); // 设置块编码
        HttpPost httpPost = new HttpPost("http://www.baidu.com");
        httpPost.setEntity(entity);
    }

    // 处理response的最简单方式， 实现ResponseHandler接口，让httpclient来管理连接的释放
    public static  void handleReponse() throws IOException {
        final CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("http://120.79.208.24:8080/admin/role/query");

        ResponseHandler<JSONObject> rh = new ResponseHandler<JSONObject>() {
            @Override
            public JSONObject handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
                StatusLine statusLine = httpResponse.getStatusLine();
                HttpEntity entity = httpResponse.getEntity();
                if(statusLine.getStatusCode() > 300) {
                    throw new HttpResponseException(
                            statusLine.getStatusCode(),
                            statusLine.getReasonPhrase());
                }

                if (entity == null) {
                    throw new ClientProtocolException("Response contains no content");
                }

                ContentType contentType = ContentType.getOrDefault(entity);
                Charset charSet = contentType.getCharset();
                Reader reader = new InputStreamReader(entity.getContent(),charSet);
                StringBuffer stringBuffer = new StringBuffer();
                int b;
                while ((b = reader.read()) != -1) {
                    stringBuffer.append((char) b);
                }

                return JSON.parseObject(stringBuffer.toString());
            }
        };

        JSONObject jsonObject = httpClient.execute(httpGet,rh);
        System.out.println(jsonObject);
    }

    public static void main(String[] args) throws IOException {
        // 返回基本协议
//        basicReponse();

        // 增加头信息
//        header();

//        getAllHeader();

//        createEntity();

        handleReponse();
    }
}
